{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3da0c960",
   "metadata": {},
   "source": [
    "# 第三讲 字符串（二）\n",
    "\n",
    "## 1. 什么是空白字符？\n",
    "\n",
    "### 1.1 什么是空白字符？\n",
    "#### (1) 空白字符的定义\n",
    "\n",
    "**空白字符**包括：\n",
    "\n",
    "- **空格**：` `\n",
    "- **制表符**：`\\t`\n",
    "- **换行符**：`\\n`\n",
    "- **回车符**：`\\r`\n",
    "\n",
    "#### (2) 空白字符的影响\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "21555a0b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "6\n",
      "7\n"
     ]
    }
   ],
   "source": [
    "# 对人类来说，这两个看起来几乎一样\n",
    "string1 = \"python\"\n",
    "string2 = \"python \"\n",
    "\n",
    "# 但对程序来说，它们是完全不同的字符串\n",
    "print(string1 == string2)  # 输出：False\n",
    "print(len(string1))        # 输出：6\n",
    "print(len(string2))        # 输出：7"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a253c63f",
   "metadata": {},
   "source": [
    "## 2. 为什么空白处理很重要？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "061b07cc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "用户名错误\n"
     ]
    }
   ],
   "source": [
    "# 用户登录场景\n",
    "stored_username = \"admin\"\n",
    "user_input = \" admin \"  # 用户输入时可能包含空白\n",
    "\n",
    "if user_input == stored_username:\n",
    "    print(\"登录成功\")\n",
    "else:\n",
    "    print(\"用户名错误\")  # 这里会输出\"用户名错误\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "dd25ddab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数据不匹配\n"
     ]
    }
   ],
   "source": [
    "# 数据处理场景\n",
    "expected = \"Python\"\n",
    "actual = \"Python \"  # 从文件或网络获取的数据可能包含空白\n",
    "\n",
    "if actual == expected:\n",
    "    print(\"数据匹配\")\n",
    "else:\n",
    "    print(\"数据不匹配\")  # 这里会输出\"数据不匹配\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c8d14e6",
   "metadata": {},
   "source": [
    "## 3. 三种删除空白的方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f2e75b08",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'python '\n",
      "'python'\n"
     ]
    }
   ],
   "source": [
    "# 1. rstrip() - 删除右端空白\n",
    "\n",
    "favorite_language = 'python '\n",
    "\n",
    "print(f\"'{favorite_language}'\")\n",
    "print(f\"'{favorite_language.rstrip()}'\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "0d4744d7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'user@example.com'\n"
     ]
    }
   ],
   "source": [
    "# 处理用户输入的邮箱地址\n",
    "email = \"user@example.com   \"\n",
    "clean_email = email.rstrip()\n",
    "print(f\"'{clean_email}'\")  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "a08f0603",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'   python'\n",
      "'python'\n"
     ]
    }
   ],
   "source": [
    "# 2. lstrip() - 删除左端空白\n",
    "favorite_language = '   python'\n",
    "\n",
    "print(f\"'{favorite_language}'\")\n",
    "print(f\"'{favorite_language.lstrip()}'\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "3756c524",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'   python   '\n",
      "'python'\n"
     ]
    }
   ],
   "source": [
    "# 3. strip() - 删除两端空白\n",
    "favorite_language = '   python   '\n",
    "\n",
    "print(f\"'{favorite_language}'\")\n",
    "print(f\"'{favorite_language.strip()}'\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "35cab925",
   "metadata": {},
   "source": [
    "## 4. 永久删除空白"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "bee9f2ae",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'python'\n",
      "'python '\n"
     ]
    }
   ],
   "source": [
    "# 临时删除\n",
    "favorite_language = 'python '\n",
    "\n",
    "print(f\"'{favorite_language.rstrip()}'\")\n",
    "print(f\"'{favorite_language}'\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "cc7c0056",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'python'\n"
     ]
    }
   ],
   "source": [
    "# 永久删除（重新赋值）\n",
    "favorite_language = 'python '\n",
    "favorite_language = favorite_language.rstrip()\n",
    "print(f\"'{favorite_language}'\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "bf1d54f7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你输入的内容是：'eada sdSD sdD'\n"
     ]
    }
   ],
   "source": [
    "# 更简洁的写法\n",
    "\n",
    "# 方法1：分步操作\n",
    "text = \"  hello  \"\n",
    "text = text.strip()\n",
    "\n",
    "# 方法2：链式操作\n",
    "text = \"  hello  \".strip()\n",
    "\n",
    "user_input = \"\"\n",
    "# 方法3：在赋值时处理\n",
    "user_input = input(f\"请输入内容：{user_input}\").strip()\n",
    "print(f\"你输入的内容是：'{user_input}'\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "49516123",
   "metadata": {},
   "source": [
    "## 5. 实际应用场景"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "70562869",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "姓名：'LUOLI'\n",
      "邮箱：'ASDGsgd@add.com'\n"
     ]
    }
   ],
   "source": [
    "# 1. 用户输入处理\n",
    "def get_clean_input(prompt):\n",
    "    \"\"\"获取用户输入并清理空白\"\"\"\n",
    "    user_input = input(prompt).strip()\n",
    "    return user_input\n",
    "\n",
    "# 使用示例\n",
    "name = get_clean_input(\"请输入您的姓名：\")\n",
    "email = get_clean_input(\"请输入您的邮箱：\")\n",
    "\n",
    "print(f\"姓名：'{name}'\")\n",
    "print(f\"邮箱：'{email}'\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "26e97a3f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2. 文件数据处理\n",
    "# 处理从文件读取的数据\n",
    "def process_file_lines(filename):\n",
    "    \"\"\"处理文件中的每一行，删除空白\"\"\"\n",
    "    with open(filename, 'r', encoding='utf-8') as file:\n",
    "        clean_lines = []\n",
    "        for line in file:\n",
    "            clean_line = line.strip()  # 删除行首行尾空白\n",
    "            if clean_line:  # 跳过空行\n",
    "                clean_lines.append(clean_line)\n",
    "    return clean_lines"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cafdd829",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3. 数据验证\n",
    "def validate_username(username):\n",
    "    \"\"\"验证用户名（删除空白后检查）\"\"\"\n",
    "    clean_username = username.strip()\n",
    "    \n",
    "    if not clean_username:\n",
    "        return False, \"用户名不能为空\"\n",
    "    \n",
    "    if len(clean_username) < 3:\n",
    "        return False, \"用户名至少需要3个字符\"\n",
    "    \n",
    "    return True, \"用户名有效\"\n",
    "\n",
    "# 测试\n",
    "test_cases = [\"admin\", \"  admin  \", \"ab\", \"   \", \"user123\"]\n",
    "for username in test_cases:\n",
    "    is_valid, message = validate_username(username)\n",
    "    print(f\"'{username}' -> {message}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "7d8b1d05",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'database_host': 'localhost', 'port': '3306', 'username': 'admin'}\n"
     ]
    }
   ],
   "source": [
    "# 4. 配置文件处理\n",
    "\n",
    "def parse_config_line(line):\n",
    "    \"\"\"解析配置文件行\"\"\"\n",
    "    line = line.strip()  # 删除行首行尾空白\n",
    "    \n",
    "    if not line or line.startswith('#'):  # 跳过空行和注释\n",
    "        return None, None\n",
    "    \n",
    "    if '=' in line:\n",
    "        key, value = line.split('=', 1)\n",
    "        return key.strip(), value.strip()  # 删除键值的空白\n",
    "    \n",
    "    return None, None\n",
    "\n",
    "# 示例配置内容\n",
    "config_lines = [\n",
    "    \"  database_host = localhost  \",\n",
    "    \"# 这是注释\",\n",
    "    \"  port = 3306  \",\n",
    "    \"\",\n",
    "    \"username=admin\"\n",
    "]\n",
    "\n",
    "config = {}\n",
    "for line in config_lines:\n",
    "    key, value = parse_config_line(line)\n",
    "    if key and value:\n",
    "        config[key] = value\n",
    "\n",
    "print(config)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0bd7edae",
   "metadata": {},
   "source": [
    "## 6. 高级用法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "937e7a3b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello world\n",
      "hello world\n"
     ]
    }
   ],
   "source": [
    "# 1. 删除特定字符\n",
    "# strip()可以删除指定字符\n",
    "text = \"...hello world...\"\n",
    "clean_text = text.strip('.')\n",
    "print(clean_text) \n",
    "\n",
    "# 删除多种字符\n",
    "text = \"!!!hello world???\"\n",
    "clean_text = text.strip('!?')\n",
    "print(clean_text) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "816d7f65",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'\\t\\n  hello world  \\r\\n'\n",
      "'hello world'\n"
     ]
    }
   ],
   "source": [
    "# 2. 处理不同类型的空白\n",
    "# 包含各种空白字符的字符串\n",
    "text = \"\\t\\n  hello world  \\r\\n\"\n",
    "print(repr(text))  # 显示所有字符\n",
    "print(repr(text.strip())) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b9649304",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['apple', 'banana', 'cherry']\n"
     ]
    }
   ],
   "source": [
    "# 3. 批量处理\n",
    "def clean_string_list(string_list):\n",
    "    \"\"\"批量清理字符串列表\"\"\"\n",
    "    return [s.strip() for s in string_list if s.strip()]\n",
    "\n",
    "# 示例\n",
    "messy_list = [\"  apple  \", \"\", \"  banana\", \"cherry  \", \"   \"]\n",
    "clean_list = clean_string_list(messy_list)\n",
    "print(clean_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ddaf490d",
   "metadata": {},
   "source": [
    "## 7. 常见错误和注意事项"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "74d9eedc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  hello  \n",
      "hello\n"
     ]
    }
   ],
   "source": [
    "# 1. 忘记重新赋值\n",
    "# 错误做法\n",
    "text = \"  hello  \"\n",
    "text.strip()  # 这不会改变text的值\n",
    "print(text) \n",
    "\n",
    "# 正确做法\n",
    "text = \"  hello  \"\n",
    "text = text.strip()\n",
    "print(text) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "d42aaa1d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2. 过度使用strip()\n",
    "def process_clean_text(text):\n",
    "    # 如果text已经是干净的，不需要再次strip()\n",
    "    return text.strip().upper().strip()  # 第二个strip()是多余的\n",
    "\n",
    "# 更好的做法\n",
    "def process_clean_text(text):\n",
    "    return text.strip().upper()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "1d4b8653",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['hello', '', 'world', '']\n"
     ]
    }
   ],
   "source": [
    "# 3. 处理None值\n",
    "def safe_strip(text):\n",
    "    \"\"\"安全的strip操作\"\"\"\n",
    "    if text is None:\n",
    "        return \"\"\n",
    "    return text.strip()\n",
    "\n",
    "# 使用示例\n",
    "values = [\"  hello  \", None, \"world\", \"\"]\n",
    "clean_values = [safe_strip(v) for v in values]\n",
    "print(clean_values)  # 输出：['hello', '', 'world', '']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ab72127a",
   "metadata": {},
   "source": [
    "## 8. 练习"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "326c927a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 练习：创建一个清理用户输入的函数\n",
    "def get_user_info():\n",
    "    name = input(\"姓名：\").strip()\n",
    "    email = input(\"邮箱：\").strip()\n",
    "    phone = input(\"电话：\").strip()\n",
    "    \n",
    "    return {\n",
    "        'name': name,\n",
    "        'email': email,\n",
    "        'phone': phone\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "231d82e0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 练习：处理多行文本\n",
    "def clean_text_block(text):\n",
    "    lines = text.split('\\n')\n",
    "    clean_lines = [line.strip() for line in lines if line.strip()]\n",
    "    return '\\n'.join(clean_lines)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "ab3e1851",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'name': '张三', 'skills': ['Python', 'Java', 'JavaScript'], 'age': 25}\n"
     ]
    }
   ],
   "source": [
    "# 练习：创建一个完整的数据清理工具\n",
    "class DataCleaner:\n",
    "    @staticmethod\n",
    "    def clean_string(text):\n",
    "        \"\"\"清理单个字符串\"\"\"\n",
    "        if not isinstance(text, str):\n",
    "            return str(text) if text is not None else \"\"\n",
    "        return text.strip()\n",
    "    \n",
    "    @staticmethod\n",
    "    def clean_list(data_list):\n",
    "        \"\"\"清理字符串列表\"\"\"\n",
    "        return [DataCleaner.clean_string(item) for item in data_list]\n",
    "    \n",
    "    @staticmethod\n",
    "    def clean_dict(data_dict):\n",
    "        \"\"\"清理字典中的字符串值\"\"\"\n",
    "        cleaned = {}\n",
    "        for key, value in data_dict.items():\n",
    "            if isinstance(value, str):\n",
    "                cleaned[key] = value.strip()\n",
    "            elif isinstance(value, list):\n",
    "                cleaned[key] = DataCleaner.clean_list(value)\n",
    "            else:\n",
    "                cleaned[key] = value\n",
    "        return cleaned\n",
    "\n",
    "# 测试\n",
    "test_data = {\n",
    "    'name': '  张三  ',\n",
    "    'skills': ['  Python  ', '  Java', 'JavaScript  '],\n",
    "    'age': 25\n",
    "}\n",
    "\n",
    "clean_data = DataCleaner.clean_dict(test_data)\n",
    "print(clean_data)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
